package com.jule.teenpatti.game.network.protocol.reqs;

import JoloProtobuf.GameSvr.JoloGame;
import com.jule.core.common.log.LoggerUtils;
import com.jule.teenpatti.base.enums.ErrorCodeEnum;
import com.jule.teenpatti.base.enums.GameConst;
import com.jule.teenpatti.game.gameUtil.GameLogic;
import com.jule.teenpatti.game.model.PlayerInfo;
import com.jule.teenpatti.game.model.eenum.PlayerStateEnum;
import com.jule.teenpatti.game.network.protocol.ClientReq;
import com.jule.teenpatti.game.network.protocol.acks.JoloGame_ApplyShowAck_50008;
import com.jule.teenpatti.game.play.AbstractTable;
import com.jule.teenpatti.game.play.TableUtil;
import com.jule.teenpatti.game.service.TableService;
import com.jule.teenpatti.game.utils.log.TableLogUtil;
import com.jule.teenpatti.game.vavle.notice.NoticeBroadcastMessages;
import com.jule.teenpatti.log.service.LogReasons;
import io.netty.buffer.ByteBuf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

//单挑时，申请开牌
public class JoloGame_ApplyShowReq_50008 extends ClientReq {
    private long time;
    private final static Logger logger = LoggerFactory.getLogger(JoloGame_ApplyShowReq_50008.class);

    public JoloGame_ApplyShowReq_50008(int functionId) {
        super(functionId);
    }

    private JoloGame.JoloGame_ApplyShowReq req;

    @Override
    public void readPayLoadImpl(ByteBuf buf) throws Exception {
        time = System.currentTimeMillis();
        byte[] blob = new byte[buf.readableBytes()];
        buf.readBytes(blob);
        req = JoloGame.JoloGame_ApplyShowReq.parseFrom(blob);
        this.setTable(TableService.getInstance().getTable(header.gameId + "", req.getRoomId(), req.getTableId()));
    }

    @Override
    public void processImpl() throws Exception {
        logger.debug("收到消息-> " + functionId + ", reqNum-> " + header.reqNum + ", req->" + req.toString());
        String userId = req.getUserId();
        String roomId = req.getRoomId();
        String tableId = req.getTableId();
        String gameOrderId = req.getGameOrderId();
        double betScore = 0;

        //获得桌子信息和玩家信息
        AbstractTable table = getTable();
        PlayerInfo player = table.getPlayer(userId);

        //初始化返回值
        JoloGame.JoloGame_ApplyShowAck.Builder ack = JoloGame.JoloGame_ApplyShowAck.newBuilder();
        ack.setUserId(userId);
        ack.setRoomId(roomId);
        ack.setTableId(tableId);
        ack.setGameOrderId(gameOrderId);
        ack.setBetScore(betScore);
        try {
            if (null == player) {
                logger.info("can't found player info, playerId->" + userId);
                ack.setResult(-1).setResultMsg(ErrorCodeEnum.GAME_50050_2.getCode());
                ctx.writeAndFlush(new JoloGame_ApplyShowAck_50008(ack.build(), header));
                return;
            }

            if (player.getSeatNum() <= 0) {
                logger.info("player have no seat,can't bet. playerId->" + userId);
                ack.setResult(-2).setResultMsg(ErrorCodeEnum.GAME_50050_2.getCode());
                ctx.writeAndFlush(new JoloGame_ApplyShowAck_50008(ack.build(), header));
                return;
            }

            if (player.getState().getValue() != PlayerStateEnum.beting.getValue()) {
                logger.warn("player state invalid,can't bet. playerId->" + userId + ", state->" + player.getState());
                ack.setResult(-3).setResultMsg(ErrorCodeEnum.GAME_50013_1.getCode());
                ctx.writeAndFlush(new JoloGame_ApplyShowAck_50008(ack.build(), header));
                return;
            }

            //判断GameOrderId是否一致
            if (!gameOrderId.equals(table.getCurrGameOrderId())) {
                ack.setResult(-4);
                logger.error("GameOrderId不匹配, currGameOrderId->" + table.getCurrGameOrderId() + ", gameOrderId->" + gameOrderId);
                ack.setResultMsg(ErrorCodeEnum.GAME_50013_2.getCode());
                ctx.writeAndFlush(new JoloGame_ApplyShowAck_50008(ack.build(), header));
                return;
            }

            //检查剩余人数是否等于两个人
            if (table.getInGamePlayers().size() != 2) {
                ack.setResult(-5);
                logger.error("未弃牌人数不等于2个人，不能show牌。inGamePlayerCnt->" + table.getInGamePlayers().size());
                ack.setResultMsg(ErrorCodeEnum.GAME_50008_1.getCode());
                ctx.writeAndFlush(new JoloGame_ApplyShowAck_50008(ack.build(), header));
                return;
            }

            //show牌的下注金额 = “补齐跟注额度”
            if (req.hasBetScore()) {
                betScore = req.getBetScore();
            } else {
                betScore = table.getCurrBaseBetScore();
                if (player.getIsBlind() == 1) {
                    betScore = betScore / 2;
                }
            }

            //检查桌面积分是否足够
            if (player.getPlayScoreStore() < betScore) {
                ack.setResult(-6);
                logger.error("score amount insufficient 。betScore->" + betScore + "：playScoreStore:" + player.getPlayScoreStore());
                ack.setResultMsg(ErrorCodeEnum.GAME_50001_4.getCode());
                ctx.writeAndFlush(new JoloGame_ApplyShowAck_50008(ack.build(), header));
                return;
            }

            //判断下注额度是否正确
            if ((player.getIsBlind() == 0 && betScore < table.getCurrBaseBetScore())
                    || (player.getIsBlind() == 1 && betScore < table.getCurrBaseBetScore() / 2)) {
                ack.setResult(-7);
                logger.error("betScore小于最低下注额，betScore->" + betScore + ", baseBetScore->" + table.getCurrBaseBetScore());
                ack.setResultMsg(ErrorCodeEnum.GAME_50008_2.getCode());
                ctx.writeAndFlush(new JoloGame_ApplyShowAck_50008(ack.build(), header));
                return;
            }
//
//            //检查是否存在被比牌用户
//            if (null == targetPlayer) {
//                ack.setResult(-8);
//                ack.setResultMsg("找不到被比牌的用户。");
//                ctx.writeAndFlush(new JoloGame_ApplyShowAck_50008(ack.build(), header));
//                return;
//            }

            if (betScore > table.getRoomConfig().getMaxBetScore()) {
                ack.setResult(-8);
                logger.error("betScore greater than maximum -> " +
                        "maxBet:" + table.getRoomConfig().getMaxBetScore() + " -> betScore:" + betScore);
                ack.setResultMsg(ErrorCodeEnum.GAME_50008_3.getCode());
                ctx.writeAndFlush(new JoloGame_ApplyShowAck_50008(ack.build(), header));
                return;
            }

            //修改玩家下注值
            player.setAlreadyBetScore4Round(betScore); //修改玩家下注值
            player.setTotalAlreadyBetScore4Hand(player.getTotalAlreadyBetScore4Hand() + betScore);//累计玩家总得下注值
            player.setCurChipsLose(player.getCurChipsLose() + betScore); //修改玩家的已投入金额

            //修改牌桌信息的玩家下注值
            table.accumulativeBet(player.getPlayerId(), betScore);

            //player.setPlayScoreStore(player.getPlayScoreStore() - betScore);//减去玩家桌面积分
            player.minusPlayScoreStore(betScore, LogReasons.CommonLogReason.GAME_SHOW); //扣除筹码并写入用户DB信息中

            //返回数据
            ack.setBetScore(betScore);
            ack.setResult(1);
            ack.setCurrPlayScore(player.getPlayScoreStore());
            ctx.writeAndFlush(new JoloGame_ApplyShowAck_50008(ack.build(), header));

            //设置牌桌信息
            table.setLastActionTime(System.currentTimeMillis()); //设置牌桌最后一次行动时间
            table.setTotalAlreadyBet(table.getTotalAlreadyBet() + betScore); //桌内累计下注金额
            table.accumulativeBet(player.getPlayerId(), betScore);

            //修改玩家状态值为已下注
            player.setState(PlayerStateEnum.already_bet);

            //发送通知
            NoticeBroadcastMessages.moneyChangeNotice(table,userId,player.getPlayScoreStore());
            //广播玩家下注
            NoticeBroadcastMessages.betRoundDoBet(table, table.getCurrRoundId(), player, null,false);

            //记录show牌双方id
            List<String> list = new ArrayList<>();
            //此处是为了show牌 发起方的vs动画头像顺序 所以list里发起方要在第一位 实际上现在桌子上只有两个人
            //但不知道目标是谁 所以需要遍历
            list.add(player.getPlayerId());
            for (PlayerInfo playerInfo : table.getInGamePlayers().values()) {
                if(!playerInfo.getPlayerId().equals(player.getPlayerId())) {
                    list.add(playerInfo.getPlayerId());
                }
            }

            //通知所有人有人show
            NoticeBroadcastMessages.bothSides(table, list);

            TableLogUtil.show(functionId, "show", userId, player.getNickName(), table.getPlayType() + "",
                    table.getRoomId(), table.getTableId(), table.getCurrGameOrderId(), betScore, TableUtil.inGamePlayersBySeatNumToString(table));

            long timeMillis = System.currentTimeMillis() - time;
            if (timeMillis > GameConst.COST_TIME) {
                LoggerUtils.performance.info("ApplyShowReq_50008,cost time:{},req:{}", timeMillis, req.toString());
            }
        } catch (Exception ex) {
//            logger.error("系统异常：userId->" + userId + ", gameOrderId->" + gameOrderId + ", message->" + ex.getMessage());
//            ack.setResult(-1);
//            ack.setResultMsg(ErrorCodeEnum.GAME_50002_2.getCode());
//            ctx.writeAndFlush(new JoloGame_ApplyShowAck_50008(ack.build(), header));
            ex.printStackTrace();
        } finally {
            logger.debug("SeeCard ACK info: " + ack.toString());
            logger.debug("SeeCard ACK bytes length: " + ack.build().toByteArray().length);
            if (null != table) {
                logger.debug("All Player info: " + System.getProperty("line.separator") + TableUtil.toStringAllPlayers(table));

                logger.debug("InGame Player info: " + System.getProperty("line.separator") + TableUtil.toStringInGamePlayers(table));
            }
            logger.debug("SeeCard over. Table state: " + table.getTableStateEnum());

            long useTimes = System.currentTimeMillis() - time;
            if(useTimes > 200) {
                logger.error("ApplyShow。 耗时->{} 毫秒, reqNum->{}", useTimes, header.reqNum); //TODO:临时增加
            }
        }
    }
}
